nginx 性能优化
一、性能优化概述
1.我们需要了解的
1.首先需要了解我们当前系统的结构和瓶颈
2.分析访问
3.其次我们需要了解业务模式
4.我们还需要了解系统层次化的结构
(根据业务需求分析架构中哪一部分需要扩展或者优化,如果业务进程访问数据库较多,则需要优化和扩展数据库,如果使用ES存储,数据使用较少,则不需要多数据库做太多的优化)
5.性能与安全
(针对公司来进行优化,如果是电商公司肯定更注重性能方面,安全方面做的不必要太高;对于金融公司,安全方面是最重要的,所以哪怕失去一部分性能也要保证安全)
2. OSI 模型考虑
1.硬件 代理(CPU) 静态(磁盘IO) 动态(cpu、内存)
2.网络 带宽、丢包、延迟
3.系统 文件描述符(文件句柄数) too many open files
4.应用 服务与服务保持长连接 http1.1
5.服务 静态资源服务优化
二、压力测试工具
1.安装ab工具
[root@web01 conf.d]
2.ab工具使用方法
[root@web01 ~]
[root@web01 conf.d]
ab: wrong number of arguments
Usage: ab [options] [http折叠://]hostname[:port]/path
3.配置tomcat静态资源
[root@web01 ~]
[root@web01 ~]
[root@web01 ~]
[root@web01 ROOT]
[root@web01 ~]
[root@web01 ~]
4.配置nginx静态资源
[root@web01 ~]
server {
listen 80;
server_name ab.linux.com;
location / {
root /code/ab;
try_files $uri $uri/ @tomcat;
index index.html;
}
location @tomcat {
proxy_pass http://172.16.1.7:8080;
}
}
[root@web01 ~]
[root@web01 ~]
[root@web01 ~]
5.ab测试页面
[root@web01 ~]
Concurrency Level: 200
Time taken for tests: 0.984 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 2420000 bytes
HTML transferred: 120000 bytes
Requests per second: 10158.27 [
Time per request: 19.688 [ms] (mean)
Time per request: 0.098 [ms] (mean, across all concurrent requests)
Transfer rate: 2400.68 [Kbytes/sec] received
[root@web01 ~]
Concurrency Level: 200
Time taken for tests: 5.646 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 2490000 bytes
HTML transferred: 130000 bytes
Requests per second: 1771.19 [
Time per request: 112.919 [ms] (mean)
Time per request: 0.565 [ms] (mean, across all concurrent requests)
Transfer rate: 430.69 [Kbytes/sec] received
6.了解影响性能指标
1、网络
(1)网络的流量
(2)网络是否丢包
(3)这些会影响http的请求与调用
2、系统
(1)硬件有没有磁盘损坏,磁盘速率
(2)系统的负载、内存、系统稳定性
3、服务
(1)连接优化。请求优化
(2)根据业务形态做对应的服务设置
4、程序
(1)接口性能
(2)处理速度
(3)程序执行效率
5、数据库
三、系统性能优化
文件句柄,Linux一切皆文件,文件句柄可以理解为就是一个索引,文件句柄会随着我们进程的调用频繁而增加,系统默认文件句柄是有限制的1024,不能让一个进程无限的调用,所以我们需要限制每个 进程和每个服务使用多大的文件句柄,文件句柄也是必须要调整的优化参数。
文件句柄的设置方式:
1、系统全局性修改。
2、用户局部性修改。
3、进程局部性修改。
1.配置文件句柄数
[root@lb01 ~]
1、系统全局性修改。
* soft nofile 25535
* hard nofile 25535
2.用户局部性修改
root soft nofile 65535
root hard nofile 65535
3.进程局部性修改
worker_rlimit_nofile 30000
2.端口重用优化
4.调整内核参数:让time_wait状态重用(端口重用)[flag]
[root@web01 ~]
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps = 1
[root@web01 ~]
[root@web01 ~]
四、代理服务优化
1.长连接语法
Syntax: keepalive connection;
Default: -
Context: upstream
2.nginx做代理服务器的优化
upstream http_backend {
server 127.0.0.1:8080;
server 127.0.0.1:8080;
keepalive 16;
}
server {
...
location /http/ {
proxy_pass http://http_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwared-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 30s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
...
}
}
3.代理PHP
upstream fastcgi_backend {
server 172.16.1.8:9000;
server 172.16.1.9:9000;
keepalive 8;
}
server {
...
location /fastcgi/ {
fastcgi_pass fastcgi_backend;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_keep_conn on;
fastcgi_connect_timeout 60s;
include fastcgi_params;
...
}
}
4.长连接方法2
Syntax: keepalive_requests number;
Default: keepalive_requests 10000;
Context: upstream
Syntax: keepalive_timeout timeout;
Default: keepalive_timeout 60s;
Context: upstream
五、静态资源优化
1.静态资源缓存
1.第一次访问
ETag: "5d8444bf-3790"
Last-Modified: Fri, 20 Sep 2019 03:17:19 GMT
2.第二次访问,请求头携带信息
If-Modified-Since: Fri, 20 Sep 2019 03:17:19 GMT
If-None-Match: "5d8444bf-3790"
3.对比响应头部返回的内容
ETag: "5d8444bf-3790"
Last-Modified: Fri, 20 Sep 2019 03:17:19 GMT
Last-Modified:服务器上文件的最后修改时间
Etag:文件标识
Expires:本地缓存目录中,文件过期的时间(由服务器指定具体的时间)
Cache-control:本地缓存目录中,文件过期的时间(由服务器指定过期的间隔时间,由于浏览器根据间隔生成具体的时间)
1、浏览器请求服务器会先进行Expires、Cache-Control的检查,检查缓存是否过期,如果没有过期则直接从缓存文件中读取。
2、如果缓存过期首先检查是否存在etag,如果存在那么客户端会向web服务器请求If-None-Match,与etag值进行比对,由服务器决策返回200还是304。
3、如果etag不存在,则进行last-Modified检查,客户端会向web服务器请求if-Modified-Since,与服务器的last-Modified进行比对,由服务器决策返回200还是304。
2.静态资源缓存时间
Syntax: expires [modified] time;
epoch | max | off;
Default: expires off;
Context: http, server, location, if in location
server {
listen 80;
server_name static.drz.com;
location ~ .*\.(jpg|gif|png)$ {
expires 7d;
}
location ~ .*\.(js|css)$ {
expires 30d;
}
}
3.开发过程中不想读取缓存
location ~ .*\.(js|css|html)$ {
add_header Cache-Control no-store;
add_header Pragma no-cache;
}
六、静态资源读取
1.sendfile语法
Syntax: sendfile on | off;
Default: sendfile off;
Context: http, server, location, if in location
2.将多个包一次发送,用于提升网络传输效率,大文件推荐打开,需要开启sendfile才行
Syntax: tcp_nopush on | off;
Default: tcp_nopush off;
Context: http, server, location
3.提高网络传输实时性,需要开启keepalive,来一个包发一个包不等待
Syntax: tcp_nodelay on | off;
Default: tcpnodelay off;
Context: http, server, location
4.一般配置
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
tcp_nodelay on;
七、静态资源压缩
1.gzip语法
Syntax: gzip on | off;
Default: gzip off;
Context: http, server, location, if in location
Syntax: gzip_types mime-type ...;
Default: gzip_types text/html;
Context: http, server, location
Syntax: gzip_comp_level level;
Default:gzip_comp_level 1;
Context: http, server, location
Syntax: gzip_http_version 1.0 | 1.1;
Default:gzip_http_version 1.1;
Context: http, server, location
2.配置压缩实例
[root@web01 code]
upstream daili {
server 10.0.0.7:8080;
keepalive 16;
}
server {
listen 80;
server_name ab.linux.com;
root /code;
index index.html;
location / {
proxy_pass http://daili;
proxy_http_version 1.1;
}
location ~ \.(jpg|png|gif|txt)$ {
gzip on;
gzip_types image/jpeg image/gif image/png text/plain;
gzip_comp_level 9;
gzip_http_version 1.1;
}
}
八、防止资源盗链
1.测试盗链页面
[root@web01 code]
server {
listen 80;
server_name ab.linux.com;
root /code;
index index.html;
location ~ \.(jpg|png|gif|txt)$ {
gzip on;
gzip_types image/jpeg image/gif image/png text/plain;
gzip_comp_level 9;
gzip_http_version 1.1;
}
}
2.防盗链配置
Syntax: valid_referers none | blocked | server_name | string ...;
Default: -;
Context: server, location
(日志格式为:10.0.0.7 - - [02/Jan/2020:15:26:08 +0800] "HEAD /2.jpg HTTP/1.1" 200 0 "-" "curl/7.29.0" "-" "-")
(日志格式为:10.0.0.7 - - [02/Jan/2020:15:27:48 +0800] "HEAD /2.jpg HTTP/1.1" 403 0 "www.baidu.com" "curl/7.29.0" "-" "-")
(日志格式为:10.0.0.7 - - [02/Jan/2020:15:31:42 +0800] "HEAD /2.jpg HTTP/1.1" 200 0 "http://static.linux.com" "curl/7.29.0" "-" "-")
3.配置web02作为资源的网站
[root@web02 conf.d]
server {
listen 80;
server_name static.linux.com;
root /code;
location / {
index index.html;
}
}
[root@web02 conf.d]
配置hosts访问测试
4.配置web01作为盗链的网站
[root@web01 conf.d]
server {
server_name dl.linux.com;
listen 80;
root /code;
location / {
index index.html;
}
}
[root@web01 conf.d]
<html>
<head>
<meta charset="utf-8">
<title>linux7.com</title>
</head>
<body style="background-color:pink;">
<center><img src="http://static.linux.com/2.jpg"/></center>
</body>
</html>
[root@web01 conf.d]
10.0.0.8 static.linux.com
5.访问页面测试
6.当然这种防护并不能百分百保证资源不被盗链,因为我们可以通过命令来修改来源的refer信息
[root@web01 conf.d]
HTTP/1.1 200 OK
Server: nginx/1.16.1
Date: Thu, 02 Jan 2020 07:31:42 GMT
Content-Type: image/jpeg
Content-Length: 12517
Last-Modified: Wed, 18 Dec 2019 01:41:33 GMT
Connection: keep-alive
ETag: "5df983cd-30e5"
Accept-Ranges: bytes
[root@web01 conf.d]
九、允许跨域访问
1.服务器迁移
2.域名更改
1.配置被跨域的网站
[root@web02 ~]
server {
listen 80;
server_name beikuayu.linux.com;
root /code;
location / {
index index.html;
}
}
[root@web02 ~]
2.配置跨域的网站
[root@web01 ~]
server {
listen 80;
server_name kuayu.linux.com;
location / {
root /code;
}
}
[root@web01 ~]
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>测试ajax和跨域访问</title>
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
</head>
<script type="text/javascript">
$(document).ready(function(){
$.ajax({
type: "GET",
url: "http://beikuayu.linux.com",
success: function(data) {
alert("sucess 卧槽 卧槽 卧槽 成功了!!!");
},
error: function() {
alert("fail!!,跨不过去啊,不让进去啊,只能蹭蹭!");
}
});
});
</script>
<body>
<h1>测试跨域访问</h1>
</body>
</html>
10.0.0.8 beikuayu.linux.com
10.0.0.7 kuayu.linux.com
4.配置允许跨域访问
[root@web02 ~]
server {
listen 80;
server_name beikuayu.linux.com;
root /code;
location / {
index index.html;
}
location ~ .*\.(html|htm)$ {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
}
}
十、CPU亲和
CPU亲和(affinity)减少进程之间不断频繁切换,减少性能损耗,其实现原理是建CPU核心和Nginx工作进程绑定方式,把每个worker进程固定到对应的cpu上执行,减少切换CPU的cache miss,获得更好的性能。
1.查看cpu
[root@tomcat01 ~]$ lscpu | grep "CPU(s)"
CPU(s): 8
On-line CPU(s) list: 0-7
NUMA node0 CPU(s): 0-7
2.配置方法
worker_processes 12;
worker_cpu_affinity 000000000001 000000000010 000000000100 000000001000 000000010000 000000100000 000001000000 000010000000 000100000000 001000000000 010000000000 10000000000;
worker_processes 2;
worker_cpu_affinity 101010101010 010101010101;
worker_processes auto;
worker_cpu_affinity auto;
3.查看绑定cpu
[root@web01 ~]
1242 nginx: master process /usr/ 2
1243 nginx: worker process 0
1244 nginx: worker process 1
1245 nginx: worker process 2
1246 nginx: worker process 3
十一、通用优化配置
[root@nginx ~]
user nginx;
worker_processes auto;
worker_cpu_affinity auto;
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;
worker_rlimit_nofile 35535;
events {
use epoll;
worker_connections 10240;
}
http {
include mime.types;
default_type application/octet-stream;
charset utf-8;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format json_access '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"url":"$uri",'
'"domain":"$host",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"status":"$status"}';
access_log /var/log/nginx/access.log json_access;
server_tokens off;
client_max_body_size 200m;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
gzip on;
gzip_disable "MSIE [1-6]\.";
gzip_http_version 1.1;
gzip_comp_level 5;
gzip_buffers 16 8k;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript image/jpeg;
include /etc/nginx/conf.d/*.conf;
}
十二、Nginx安全与优化总结
1、CPU亲和、worker进程数、调整每个worker进程打开的文件数
2、使用epoll网络模型、调整每个worker进程的最大连接数
3、文件的高效读取sendfile、nopush
4、文件的传输实时性、nodealy
5、开启tcp长连接,以及长连接超时时间keepalived
6、开启文件传输压缩gzip
7、开启静态文件expires缓存
8、隐藏nginx版本号
9、禁止通过ip地址访问,禁止恶意域名解析,只允许域名访问
10、配置防盗链、以及跨域访问
11、防DDOS、cc攻击,限制单IP并发连接,以及http请求
12、优雅显示nginx错误页面
13、nginx加密传输https优化
14、nginx proxy_cache、fastcgi_cache、uwsgi_cache 缓存,第三方工具(squid、varnish)
十三、php优化
php程序配置管理文件/etc/php.ini,主要调整日志、文件上传、禁止危险函数、关闭版本号显示等
1.php.ini优化配置
expose_php = Off
display_error = Off
error_reporting = E_ALL
log_errors = On
error_log = /var/log/php_error.log
date.timezone = Asia/Shanghai
file_uploads = On
upload_max_filesize = 300M
post_max_size = 300M
max_file_uploads = 20
memory_limit = 128M
[Session]
session.save_handler = redis
session.save_path = "tcp://172.16.1.51:6379"
disable_functions = chown,chmod,pfsockopen,phpinfo
2.php禁止函数
phpinfo()
功能描述:输出 PHP 环境信息以及相关的模块、WEB 环境等信息。
危险等级:中
passthru()
功能描述:允许执行一个外部程序并回显输出,类似于 exec()。
危险等级:高
exec()
功能描述:允许执行一个外部程序(如 UNIX Shell 或 CMD 命令等)。
危险等级:高
system()
功能描述:允许执行一个外部程序并回显输出,类似于 passthru()。
危险等级:高
chroot()
功能描述:可改变当前 PHP 进程的工作根目录,仅当系统支持 CLI 模式
PHP 时才能工作,且该函数不适用于 Windows 系统。
危险等级:高
scandir()
功能描述:列出指定路径中的文件和目录。
危险等级:中
chgrp()
功能描述:改变文件或目录所属的用户组。
危险等级:高
chown()
功能描述:改变文件或目录的所有者。
危险等级:高
shell_exec()
功能描述:通过 Shell 执行命令,并将执行结果作为字符串返回。
危险等级:高
proc_open()
功能描述:执行一个命令并打开文件指针用于读取以及写入。
危险等级:高
proc_get_status()
功能描述:获取使用 proc_open() 所打开进程的信息。
危险等级:高
error_log()
功能描述:将错误信息发送到指定位置(文件)。
安全备注:在某些版本的 PHP 中,可使用 error_log() 绕过 PHP safe mode,
执行任意命令。
危险等级:低
ini_alter()
功能描述:是 ini_set() 函数的一个别名函数,功能与 ini_set() 相同。
具体参见 ini_set()。
危险等级:高
ini_set()
功能描述:可用于修改、设置 PHP 环境配置参数。
危险等级:高
ini_restore()
功能描述:可用于恢复 PHP 环境配置参数到其初始值。
危险等级:高
dl()
功能描述:在 PHP 进行运行过程当中(而非启动时)加载一个 PHP 外部模块。
危险等级:高
pfsockopen()
功能描述:建立一个 Internet 或 UNIX 域的 socket 持久连接。
危险等级:高
syslog()
功能描述:可调用 UNIX 系统的系统层 syslog() 函数。
危险等级:中
readlink()
功能描述:返回符号连接指向的目标文件内容。
危险等级:中
symlink()
功能描述:在 UNIX 系统中建立一个符号链接。
危险等级:高
popen()
功能描述:可通过 popen() 的参数传递一条命令,并对 popen() 所打开的文件进行执行。
危险等级:高
stream_socket_server()
功能描述:建立一个 Internet 或 UNIX 服务器连接。
危险等级:中
putenv()
功能描述:用于在 PHP 运行时改变系统字符集环境。在低于 5.2.6 版本的 PHP 中,可利用该函数
修改系统字符集环境后,利用 sendmail 指令发送特殊参数执行系统 SHELL 命令。
危险等级:高
禁用方法如下:
打开/etc/php.ini文件,
查找到 disable_functions ,添加需禁用的函数名,如下:
phpinfo,eval,passthru,exec,system,chroot,scandir,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_alter,ini_restore,dl,pfsockopen,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,fsocket,fsockopen
3.php-fpm进程管理配置文件/etc/php-fpm.conf
include=/etc/php-fpm.d/*.conf
[global]
pid = /var/log/php-fpm/php-fpm.pid
error_log = /var/log/php-fpm/php-fpm.log
log_level = error
rlimit_files = 65535
events.mechanism = epoll
[www]
user = www
group = www
;listen = /dev/shm/php-fpm.sock
listen = 127.0.0.1:9000
;listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 512
pm.start_servers = 32
pm.min_spare_servers = 32
pm.max_spare_servers = 64
pm.max_requests = 1500
pm.process_idle_timeout = 15s;
pm.status_path = /phpfpm_status
php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/phpfpm_error.log
php_admin_flag[log_errors] = on
request_slowlog_timeout = 5s
slowlog = /var/log/php_slow.log
[21-Nov-2013 14:30:38] [pool www] pid 11877
script_filename = /usr/local/lnmp/nginx/html/www.quancha.cn/www/fyzb.php
[0xb70fb88c] file_get_contents() /usr/local/lnmp/nginx/html/www.quancha.cn/www/fyzb.php:2
4.配置nginx开启php-fpm监控模块
[root@web01 ~]
pm.status_path = /phpfpm_status
server {
listen 80;
server_name php.drz.com;
root /code;
location / {
index index.php index.html;
}
location /phpfpm_status {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
5.状态页面分析
[root@nginx ~]
pool: www
process manager: dynamic
start time: 20/Jan/2018:00:00:09 +0800
start since: 409
accepted conn: 22
listen queue: 0
max listen queue: 0
listen queue len: 128
idle processes: 4
active processes: 1
total processes: 5
max active processes: 2
max children reached: 0
6./etc/php-fpm.d/www.conf
[global]
pid = /var/run/php-fpm.pid
error_log = /var/log/php-fpm.log
log_level = warning
rlimit_files = 655350
events.mechanism = epoll
[www]
user = nginx
group = nginx
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 512
pm.start_servers = 32
pm.min_spare_servers = 32
pm.max_spare_servers = 64
pm.process_idle_timeout = 15s;
pm.max_requests = 2048
pm.status_path = /phpfpm_status
php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/php/php-www.log
php_admin_flag[log_errors] = on
request_slowlog_timeout = 5s
slowlog = /var/log/php-slow.log
十四、优化总结
1.nginx优化
1.硬件
nginx作为代理服务器,需要提高他的内存和cpu
nginx作为静态文件服务器,需要配置很大的磁盘
2.网络
带宽给的大一些
丢包处理
3.系统
打开文件句柄数
长连接time_wait端口重用
4.应用
nginx作为代理,长连接
5.服务
nginx作为静态网站:静态缓存、静态资源读取、静态资源压缩、防盗链、跨域访问、cpu亲和
2.php优化
1.php.ini
打开日志、禁止函数(研发沟通)
2.php-fpm
打开日志、日志级别
3.php-fpm.d/www.conf
进程管理
4.php状态页面
开启状态页面,可以用来监控php状态
5.php慢日志